package com.xuelang.pipeline.app.resource.impl;

import cn.hutool.core.util.IdUtil;
import com.xuelang.jadp.client.sys.dto.UserInfoDTO;
import com.xuelang.pipeline.app.resource.SpaceService;
import com.xuelang.pipeline.app.resource.converter.SpaceDTOToSpaceConverter;
import com.xuelang.pipeline.client.common.constant.Constant;
import com.xuelang.pipeline.client.common.exception.BizException;
import com.xuelang.pipeline.client.common.request.PageParam;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.common.util.BizAssert;
import com.xuelang.pipeline.client.resource.dto.SpaceDTO;
import com.xuelang.pipeline.client.resource.dto.SpaceQuery;
import com.xuelang.pipeline.domain.resource.Space;
import com.xuelang.pipeline.domain.resource.service.ClusterDomainService;
import com.xuelang.pipeline.domain.resource.service.EnvironmentDomainService;
import com.xuelang.pipeline.domain.resource.service.SpaceDomainService;
import com.xuelang.sys.app.sys.UserManagerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 空间服务实现类
 *
 * @author xiwen.zxg
 * @since 2024/5/15
 */
@Service
public class SpaceServiceImpl implements SpaceService {

    @Autowired
    SpaceDomainService spaceDomainService;
    @Autowired
    ClusterDomainService clusterDomainService;
    @Autowired
    EnvironmentDomainService environmentDomainService;
    @Autowired
    UserManagerService userManagerService;

    private SpaceDTO fullfillCreator(SpaceDTO spaceDTO){
        UserInfoDTO user = userManagerService.getUserById(spaceDTO.getCreatorId());
        if (Objects.nonNull(user)) {
            spaceDTO.setCreator(user.getRealName());
        }else{
            spaceDTO.setCreator(Constant.UNKNOWN_USER);
        }
        return spaceDTO;
    }


    @Override
    public PageRecord<SpaceDTO> pageList(PageParam<SpaceQuery> dtoPageParam) {
        SpaceQuery condition = dtoPageParam.getCondition();
        condition = condition == null ? new SpaceQuery() : condition;
        PageRecord<Space> pageRecord = spaceDomainService.pageList(
                dtoPageParam.getCurrentPage(),
                dtoPageParam.getPageSize(),
                condition);
        return new PageRecord<>(
                pageRecord.getCurrentPage(),
                pageRecord.getPageSize(),
                pageRecord.getTotalCount(),
                pageRecord.getTotalPages(),
                pageRecord.getRecords().stream()
                        .map(SpaceDTOToSpaceConverter.INSTANCE::spaceToSpaceDTO)
                        .map(this::fullfillCreator)
                        .collect(Collectors.toList())
        );
    }

    @Override
    public List<SpaceDTO> list(SpaceQuery spaceQuery) {
        return spaceDomainService.list(spaceQuery).stream()
                .map(SpaceDTOToSpaceConverter.INSTANCE::spaceToSpaceDTO)
                .map(this::fullfillCreator)
                .collect(Collectors.toList());
    }


    @Override
    public Boolean add(SpaceDTO spaceDTO) {
        BizAssert.notNull(spaceDTO.getNamespace(), "命名空间不能为空");
        BizAssert.notNull(spaceDTO.getClusterUuid(), "集群唯一标识不能为空");
        BizAssert.notNull(spaceDTO.getCode(), "交付空间编码不能为空");
        BizAssert.notNull(spaceDTO.getName(), "交付空间名称不能为空");
        BizAssert.notNull(spaceDTO.getProjectCode(), "交付空间所属项目不可为空");
        BizAssert.isTrue(clusterDomainService.existsCluster(spaceDTO.getClusterUuid()), "对应的集群唯一标识不存在");
//        BizAssert.assertPatternValid(spaceDTO.getName(), "^[a-zA-Z0-9\u4e00-\u9fa5-_]{0,20}$", "名称格式不正确，只能大小子字母，数字，中文，下划线（_）和中划线（-）");
//        BizAssert.assertPatternValid(spaceDTO.getCode(), "^(?!-)[a-z0-9-_]{1,50}(?<!-)$", "编码格式不正确，只能是小写字母，数字，中划线（-）,下划线（_），中划线不能开头结尾");
        Space space = SpaceDTOToSpaceConverter.INSTANCE.spaceDTOToSpace(spaceDTO);
        space.setUuid(IdUtil.fastSimpleUUID());
        return spaceDomainService.save(space);
    }

    @Override
    public Boolean update(SpaceDTO spaceDTO) {
        BizAssert.notNull(spaceDTO.getUuid(), "交付空间唯一标识不能为空");
        BizAssert.notNull(spaceDTO.getNamespace(), "命名空间不能为空");
        BizAssert.notNull(spaceDTO.getClusterUuid(), "集群唯一标识不能为空");
        BizAssert.notNull(spaceDTO.getCode(), "交付空间编码不能为空");
        BizAssert.notNull(spaceDTO.getName(), "交付空间名称不能为空");
        BizAssert.notNull(spaceDTO.getProjectCode(), "交付空间所属项目不可为空");
//        BizAssert.assertPatternValid(spaceDTO.getName(), "^[a-zA-Z0-9\u4e00-\u9fa5-_]{0,20}$", "名称格式不正确，只能大小子字母，数字，中文，下划线（_）和中划线（-）");
//        BizAssert.assertPatternValid(spaceDTO.getCode(), "^(?!-)[a-z0-9-_]{1,50}(?<!-)$", "编码格式不正确，只能是小写字母，数字，中划线（-）,下划线（_），中划线不能开头结尾");
        Space space = SpaceDTOToSpaceConverter.INSTANCE.spaceDTOToSpace(spaceDTO);
        return spaceDomainService.update(space);
    }

    @Override
    public Boolean delete(String uuid) {
        BizAssert.notNull(uuid, "交付空间唯一标识不能为空");
        // 已经被应用下环境绑定的交付空间，不能删除
        if (environmentDomainService.existsEnvironmentBySpaceUuid(uuid)) {
            throw new BizException("该交付空间已经被环境绑定，请先解绑后删除!");
        }
        return spaceDomainService.delete(uuid);
    }

    @Override
    public SpaceDTO query(String uuid) {
        BizAssert.notNull(uuid, "交付空间唯一标识不能为空");
        return SpaceDTOToSpaceConverter.INSTANCE.spaceToSpaceDTO(spaceDomainService.query(uuid));
    }

    @Override
    public Boolean existsEnvironmentBySpaceUuid(String spaceUuid) {
        return environmentDomainService.existsEnvironmentBySpaceUuid(spaceUuid);
    }
}
